//
// Created by liu_zongchang on 2023/11/9.
// Email 1439797751@qq.com
//

#include <QFrame>
#include <QMouseEvent>
#include "DoubleSlider.h"
#include <QDebug>

DoubleSlider::DoubleSlider(QWidget *parent) : QWidget(parent){
    //设置鼠标追踪
    this->setMouseTracking(true);

    m_slider = new QFrame(this);
    m_slider->setStyleSheet("QFrame{background:rgb(215,215,215);"
                            "border:none;"
                            "border-radius:2px;}");
    m_progress = new QFrame(this);
    m_progress->setStyleSheet("QFrame{background:rgb(45,118,127);border:none;border-radius:2px;}");
    m_handle = new QFrame(this);
    m_handle->setStyleSheet("QFrame{background:rgb(45,118,127);"
                            "border:none;"
                            "border-radius:7px;}");
    //设置其固定大小
    m_handle->setFixedSize(15, 15);
    //this->setFixedSize(200, 30);
}

//这里只有显式调用resize才会触发该事件
void DoubleSlider::resizeEvent(QResizeEvent *event) {
    (void)event;
    m_slider->setFixedSize(this->width() - 10, 4);
    m_slider->move(5, (this->height() - m_slider->height()) / 2);
    //移动handle（从0开始移动）
    m_handle->move(0, (this->height() - m_handle->height()) / 2);
    updateProgress();
}

//鼠标点击事件
void DoubleSlider::mousePressEvent(QMouseEvent *event) {
    QWidget::mousePressEvent(event);
    //检测是否是通过鼠标左键点击的
    if(event->button() == Qt::LeftButton){

        m_mousePressed = true;
        //记录鼠标的坐标
        m_mousePoint = event->pos();

        if(m_handle->geometry().contains(event->pos())){
            m_mouseInHandle = true;
        }else if(m_slider->geometry().contains(event->pos())){
            //如果光标此时在槽的控件范围内
            m_value += m_step;
            if(m_value > m_maxValue){
                //限制m_value的取值范围
                m_value = m_maxValue;
            }
            //移动handle（获取当前数值占整个滑动槽数值的百分比）
            double handlePercent = 1.0 * (m_value - m_minValue) / (m_maxValue - m_minValue);
            //通过这一个式子来保证滑动槽与滑块的位置恰好与他们数值比是等比例的，便于用户实际观察，如果仅仅设置固定数值可扩展性就没有这么强了。
            //（当前样式就只需要修改m_maxValue与m_minValue的值即可改变滑动槽的表示范围，还能保证其每次拖动都是成比例的）
            m_handle->move((int) ((this->width() - m_handle->width()) * handlePercent), (this->height() - m_handle->height()) / 2);
            updateProgress();
            //
            emit valueChanged(m_value);
        }
    }
}

//鼠标移动事件
void DoubleSlider::mouseMoveEvent(QMouseEvent *event) {
    QWidget::mouseMoveEvent(event);
    //QMouseEvent中buttons方法用于判断鼠标当前的被按下按钮
    if(m_mousePressed && event->buttons() != 0) {
        //鼠标拖动滑块的情况下
        if(m_mouseInHandle){
            //鼠标仍在按住滑块的情况下
            //移动handle（handleX表示滑块横坐标的最新位置）
            int handleX = m_handle->x() + event->pos().x() - m_mousePoint.x();
            if(handleX < 0) {
                //数据错误情况
                handleX = 0;
            } else if (handleX > this->width() - m_handle->width()) {
                //当滑块拖动距离超过了滑动槽的宽度
                handleX = this->width() - m_handle->width();
            }
            //handleX表示滑块新的坐标
            m_handle->move(handleX, (this->height() - m_handle->height()) / 2);
            m_mousePoint = event->pos();
            //通过滑块占滑动槽的百分比计算m_value的值
            double handlePercent = (double)handleX / (this->width() - m_handle->width());
            m_value = m_minValue + (m_maxValue - m_minValue) * handlePercent;

            updateProgress();
            emit valueChanged(m_value);
        }
    }
}

//鼠标离开事件
void DoubleSlider::mouseReleaseEvent(QMouseEvent *event) {
    QWidget::mouseReleaseEvent(event);
    //更新鼠标点击滑块状态
    m_mousePressed = false;
    if(!m_handle->geometry().contains(event->pos())){
        //如果鼠标不在滑块的几何图像（控件坐标）范围内
        m_mouseInHandle = false;
    }
    qDebug() << "m_Value: " << m_value;
}

//鼠标滚轮事件
void DoubleSlider::wheelEvent(QWheelEvent *event) {
    QWidget::wheelEvent(event);
    //angleDelta表示鼠标滚轮的值，返回一个QPoint对象，其中x表示水平移动（按住shfit滚轮进入水平滚动），y表示垂直移动（正常情况默认垂直滚动）
    //其中滚动的角度为QPoint对象中的值乘上1/8（偏移量）就能获得滚轮旋转的角度了
    if (event->angleDelta().y() > 0) {
        //滚轮按照m_step作为步长增长
        m_value += m_step;
        if (m_value > m_maxValue) {
            m_value = m_maxValue;
        }
    } else {
        m_value -= m_step;
        if (m_value < m_minValue) {
            m_value = m_minValue;
        }
    }
    //移动handle
    double handlePercent = 1.0 * (m_value - m_minValue) / (m_maxValue - m_minValue);
    m_handle->move((int) ((this->width() - m_handle->width()) * handlePercent), (this->height() - m_handle->height()) / 2);
    updateProgress();
    emit valueChanged(m_value);
}

//鼠标进入控件事件
void DoubleSlider::enterEvent(QEvent *event) {
    QWidget::enterEvent(event);
}

//鼠标离开事件
void DoubleSlider::leaveEvent(QEvent *event) {
    QWidget::leaveEvent(event);
}

//更新控件UI
void DoubleSlider::updateProgress() {
      //更新槽的大小以及位置
     m_progress->setFixedSize(m_handle->x() + 1, m_slider->height());
     m_progress->move(0, (this->height() - m_progress->height()) / 2);
}

//设置滑块的取值范围
void DoubleSlider::setRange(double minValue, double maxValue) {
    m_minValue = minValue;
    m_maxValue = maxValue;
    updateProgress();
}

void DoubleSlider::setMinValue(double minValue) {
    m_minValue = minValue;
    updateProgress();
}

void DoubleSlider::setMaxValue(double maxValue) {
    m_maxValue = maxValue;
    updateProgress();
}

void DoubleSlider::setValue(double value) {
    if(value == (int)m_value){
        return;
    }

    m_value = value;
    if(m_value < m_minValue){
        m_value = m_minValue;
    }else if(m_value > m_maxValue){
        m_value = m_maxValue;
    }
    //移动handle
    double handlePercent = 1.0 * (m_value - m_minValue) / (m_maxValue - m_minValue);
    m_handle->move((int) ((this->width() - m_handle->width()) * handlePercent), (this->height() - m_handle->height()) / 2);
    updateProgress();
}

void DoubleSlider::setStep(double step) {
    m_step = step;
}
